namespace ScrumSprintMonitor.UI.Wpf.ViewModels
{
	#region #using Directives

	using System;
	using System.Diagnostics;
	using System.Threading;
	using System.Windows.Threading;

	using ContinuousLinq.Reactive;

	using PostSharp;

	#endregion

	public class ViewModelBase : ReactiveObject,
	                             IFirePropertyChanged,
	                             IDisposable
	{
		private readonly SynchronizationContext syncContext;
		private bool disposed;

		protected ViewModelBase()
		{
			this.syncContext = SynchronizationContext.Current;
		}

		protected SynchronizationContext SyncContext
		{
			[DebuggerStepThrough]
			get { return this.syncContext; }
		}

		protected bool Disposed
		{
			[DebuggerStepThrough]
			get { return this.disposed; }
		}

		#region IFirePropertyChanged Members

		void IFirePropertyChanged.OnPropertyChanged(string propertyName)
		{
			OnPropertyChanged(propertyName);
		}

		#endregion

		~ViewModelBase()
		{
			Dispose(false);
		}

		protected void PostAction(Action action)
		{
			if (SyncContext == null)
			{
				action();
			}
			else
			{
				Dispatcher.BeginInvoke(action);
			}
		}

		protected void PostAction(DispatcherPriority priority, Action action)
		{
			if (SyncContext == null)
			{
				action();
			}
			else
			{
				Dispatcher.BeginInvoke(priority, action);
			}
		}

		protected internal void GuardDisposed()
		{
			if (this.disposed)
			{
				throw new ObjectDisposedException(GetType().Name);
			}
		}

		#region Implementation of IDisposable

		public void Dispose()
		{
			Dispose(true);

			GC.SuppressFinalize(this);
		}

		protected virtual void Dispose(bool disposing)
		{
			if (disposing)
			{
				SuppressPropertyChanged = true;
			}

			this.disposed = true;
		}

		#endregion
	}
}